package cConfig

import (
	"fmt"
	"os"
	"regexp"
	"strings"

	"gitee.com/csingo/cLog"
)

type ReplaceFunc func(s, old, new string) string
type ReadFunc func(id, group string, explain bool) (result string, err error)

type ExplainItem struct {
	Reg         string      `json:"reg"`
	Source      string      `json:"source"`
	Target      string      `json:"target"`
	DataID      string      `json:"data_id"`
	GroupID     string      `json:"group_id"`
	ReplaceFunc ReplaceFunc `json:"-"`
	ReadFunc    ReadFunc    `json:"-"`
}

const (
	ExplainRegexpText  = `\$text\{([\w_\-\/]+)(\.?([\w_\-]+))?\}`                        // 字符串替换字符串
	ExplainRegexpJson  = `\"\$json\{([\w_\-\/]+)(\.?([\w_\-]+))?\}\"`                    // 字符串替换对象
	ExplainRegexpArray = `\"\$(array|jsonArray|slice)\{([\w_\-\/]+)(\.?([\w_\-]+))?\}\"` // 数组添加元素
	ExplainRegexpEnv   = `\"\$env\{([\w_]+)(\.(string|int|bool|number))\}\"`             // 数组添加元素
)

var AllExplainRegexp = map[string]ReplaceFunc{
	ExplainRegexpText:  strings.ReplaceAll,
	ExplainRegexpJson:  strings.ReplaceAll,
	ExplainRegexpArray: ReplaceSlice,
	ExplainRegexpEnv:   strings.ReplaceAll,
}

func ReplaceSlice(s, old, new string) string {
	new = strings.TrimLeft(new, "[")
	new = strings.TrimRight(new, "]")
	new = strings.Trim(new, "\n")
	new = strings.Trim(new, "\r\n")

	return strings.ReplaceAll(s, old, new)
}

func ReadEnv(id, group string, explain bool) (result string, err error) {
	result = os.Getenv(id)
	if strings.Contains(result, `"`) {
		result = strings.ReplaceAll(result, `"`, `\"`)
	}
	if group == "string" {
		result = fmt.Sprintf(`"%s"`, result)
	}

	return
}

func Explain(client ClientInterface, content string) (result []*ExplainItem, err error) {
	result = make([]*ExplainItem, 0)
	for reg, replaceFunc := range AllExplainRegexp {
		matches := regexp.MustCompile(reg).FindAllStringSubmatch(content, -1)
		for _, match := range matches {
			item := &ExplainItem{
				Reg:         reg,
				Source:      match[0],
				Target:      "",
				DataID:      match[1],
				GroupID:     match[3],
				ReplaceFunc: replaceFunc,
				ReadFunc:    client.ReadConf,
			}
			switch reg {
			case ExplainRegexpEnv:
				item.ReadFunc = ReadEnv
			}
			item.Target, err = item.ReadFunc(item.DataID, item.GroupID, false)
			if err != nil {
				cLog.WithContext(nil, map[string]any{
					"source": "cConfig.Explain",
					"item":   item,
					"err":    err.Error(),
				}, []cLog.Option{
					cLog.IncludePaths{},
				}).Errorf("配置读取异常: %s", client.Driver())
				return
			}
			result = append(result, item)
		}
	}
	return
}
